﻿#ifndef _FD_MODELDB_H_
#define _FD_MODELDB_H_ 

#include "../dll_cfg.h"
#include "udataset/mdb/ModelDataStream.h"
#include "udataset/mdb/ModelTree.h"

#ifndef FDB_LINUX
#include "math/OgreMatrix4.h"
#endif

#include "kernel/OgreIntVector.h"
#include "udataset/CommonDef.h"
#include "kernel/time/time.h"
#include "udataset/mdb/CommonStruct.h"

namespace FD
{
	namespace Utility
	{
		namespace Dataset
		{
			class ModelDataSource;
			class ModelMetaInfo;
#ifndef FDB_LINUX
			typedef struct ComponentTime
			{
				uint32 id;
				FD::Kernel::Time fromDate;
				FD::Kernel::Time toDate;
				String comp;
				float percent;

				ComponentTime()
				{
					id = 0;
					percent = 0.0;
				}

			}ComponentTime;

			typedef std::vector<ComponentTime> ComponentTimeVec;

			typedef struct ComponentTimeline
			{
				FD::Kernel::Time fromDate;
				FD::Kernel::Time toDate;

				ComponentTimeVec timeVec;
			}ComponentTimeline;


			class FD_XDataset_Export ModelRecord
			{
				friend class ModelDB;
			protected:
				ModelRecord(const String& n)
				{
					dbName = n;
					meshID = 0;
					metaInfo = NULL;
				}
				
				C_DISABLE_COPY(ModelRecord);
			public:
				~ModelRecord();

				uint32 meshID;

				String dbName;
				String meshName;
				SimpleBound meshBound;

				FD::Kernel::Math::Matrix4 localMatrix;

				ModelDataStream meshStream;

				ModelMetaInfo* metaInfo;

				FD::Kernel::MemoryDataStreamPtr meshBoundStream;
				FD::Kernel::MemoryDataStreamPtr localMatrixStream;

				void matrixToStream();
				void matrixFromStream();

				void boundToStream();
				void boundFromStream();

				ModelRecord* clone();
			};
#endif

			class FD_XDataset_Export ModelDB 
			{
				friend class ModelDataSource;
				friend struct CompInfoPage;
				friend struct TaskPage;
				friend struct PModelInfoPage;
				friend struct ModelTreePage;
			public:
				virtual ~ModelDB();

				//事务，可选择是否开启
				void transaction();
				void commit(bool save = true);
				void autoTransaction(bool flag);
				void setTrasNum(uint32 transNum){mTransNum = transNum;}

				uint32 getID(){return mDBID;}
				String getName(){return mDBName;}
				ModelDataSource* getDataSource(){return mpDataSource;}

#ifndef FDB_LINUX
				void setSameNameMode(SameNameMode mode){mSameNameMode = mode;}
				SameNameMode getSameNameMode(){return mSameNameMode;}

				bool updateModelTreeBox(uint32 modelID, uint32 treeID, SimpleBound& box);
				/*************************遍历模型对象************************/
				FD::Kernel::IntVector getModelRecordIDs();
				/*************************模型对象************************/
				ModelRecord* createModelRecord();
				uint32 insertModelRecord(ModelRecord* record);
				void deleteModelRecord(uint32 modelID);
				void clearModelRecord();

				FD::Kernel::IntVector existsModelRecord(const String& modelName);
				uint32 existsModelRecord(uint32 modelID);
				FD::Kernel::IntVector existsTextureRecord(const String& texName);
				uint32 existsTextureRecord(uint32 texID);
				ModelRecord* queryModelAttrByID(uint32 modelID);
				ModelRecord* queryModelAttrByName(const String& modelName);
				ModelRecord* queryModelRecordByName(const String& modelName);
				ModelRecord* queryModelRecordByID(uint32 modelID);
				ModelRecord* queryModelRecordWithThumbTextureByID(uint32 modelID);
				bool queryOrigTextureByID(uint32 modelID, ModelDataStream::SharedTextureVec& texVec);
				bool queryThumbTextureByID(uint32 modelID, ModelDataStream::SharedTextureVec& texVec);

				/*************************复合模型对象************************/
				FD::Kernel::IntVector getCompositeModelRecordIDs();
				bool getCompositeModelRefIDs(uint32 modelID, FD::Kernel::IntVector& ids, FD::Kernel::StringVector& names);

				/*************************模型属性树***********************/
				bool createModelTree(uint32 modelID);
				void deleteModelTree(uint32 modelID);
				uint32 insertModelTreeRecord(uint32 modelID, ModelTree* tree);
				void deleteModelTreeRecord(uint32 modelID, uint32 treeID);

				ModelTree* queryModelTreeByName(const String& modelName);
				ModelTree* queryModelTreeByID(uint32 modelID);
				ModelTree* queryModelTreeByGuid(uint32 modelID, const String& guid);
				ModelTree* queryModelTreeByGuid(const String& modelName, const String& guid);

				ModelTreeVec queryModelChildrenTree(uint32 modelID, uint32 treeID);
				ModelTreeVec queryModelChildrenTree(const String& modelName, uint32 treeID);

				ModelTree* queryModelAllTree(const String& modelName);
				ModelTree* queryModelAllTree(uint32 modelID);

				void queryModelTreeComponentTimeline(uint32 modelID, ComponentTimeline& timeline);
				void queryModelTreeComponentTimeline(const String& modelName, ComponentTimeline& timeline);

				/*************************复合模型属性树***********************/
				uint32 existsCompositeModelTree(const String& modelName);
				bool existsCompositeModelTree(uint32 modelID, String& modelName);
				uint32 createCompositeModelTree(const String& modelName);
				void deleteCompositeModelTree(uint32 modelID);
				uint32 insertCompositeModelTreeRecord(uint32 modelID, ModelTree* tree);
				void deleteCompositeModelTreeRecord(uint32 modelID, uint32 treeID);

				ModelTree* queryCompositeModelTreeByName(const String& modelName);
				ModelTree* queryCompositeModelTreeByID(uint32 modelID);
				ModelTree* queryCompositeModelTreeByGuid(uint32 modelID, const String& guid);
				ModelTree* queryCompositeModelTreeByGuid(const String& modelName, const String& guid);

				ModelTreeVec queryCompositeModelChildrenTree(uint32 modelID, uint32 treeID);
				ModelTreeVec queryCompositeModelChildrenTree(const String& modelName, uint32 treeID);

				ModelTree* queryCompositeModelAllTree(const String& modelName);
				ModelTree* queryCompositeModelAllTree(uint32 modelID);

				void queryCompositeModelTreeComponentTime(uint32 modelID, ComponentTimeline& timeline);
				void queryCompositeModelTreeComponentTime(const String& modelName, ComponentTimeline& timeline);		
#endif

				/*************************瓦块模型属性树***********************/

				/*
				* 函数功能： 获取所有导入的PModel列表
				* 参    数：
				PModelInfoVec [out] : 传出的信息列表
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelInfo(PModelInfoVec& rtn);

				/*
				* 函数功能： 获取所有导入的PModel列表 -- 分页
				* 参    数：
				uint32 recordNumPerPage [in] : 每页记录条数
				PModelInfoPage [out] : 传出的信息列表
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelInfo_Page(uint32 recordNumPerPage, PModelInfoPage& page);

				/*
				* 函数功能： 根据PModel名称获取对应的modelID
				* 参    数：
				const String &modelName [in] : PModel名称
				* 返 回 值：0失败，否则为PModel对应的ID
				*/
				uint32 existsPModel(const String& modelName);
				
				/*
				* 函数功能： 根据PModel的ID查询结构树根节点
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				ModelTree*& [out] : 根节点，只有当前节点信息，不包含子节点。注意：内存用完需要释放，releaseModelTree
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelRootTree(uint32 modelID, ModelTree*& rtn);

				/*
				* 函数功能： 查询PModel的结构树子节点
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& parentGuid [in] : 父guid
				ModelTreeVec &rtn [out] : 子节点集合，不包含子节点下一级节点。注意：内存用完需要释放，releaseModelTreeVec
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelChildTree(uint32 modelID, const String& parentGuid, ModelTreeVec& rtn);

				/*
				* 函数功能： 查询PModel的结构树子节点
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& parentGuid [in] : 父guid
				uint32 recordNumPerPage [in] : 每页记录条数
				ModelTreePage &rtn [out] : 子节点集合，不包含子节点下一级节点。
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelChildTree_Page(uint32 modelID, const String& parentGuid, uint32 recordNumPerPage, ModelTreePage& page);

				/*
				* 函数功能： 直接根据Guid查询某一级子节点
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& guid [in] : 条件guid
				ModelTree*& [out] : 当前节点信息，注意：内存用完需要释放，releaseModelTree
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelTreeByGuid(uint32 modelID, const String& guid, ModelTree*& rtn);

				/*
				* 函数功能： 直接根据Guid查询某父节点
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& guid [in] : 条件guid
				ModelTree*& [out] : 父节点信息，注意：内存用完需要释放，releaseModelTree
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelParentTreeByGuid(uint32 modelID, const String& guid, ModelTree*& rtn);

				/*
				* 函数功能： 根据guid查询构件属性
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& guid [in] : 条件guid
				CompAttr& [out] : 构件属性
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompAttr(uint32 modelID, const String& guid, CompAttr& rtn);

				/*
				* 函数功能： 根据tag查询构件属性
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& tag [in] : 条件tag
				CompAttr& [out] : 构件属性
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompAttrByTag(uint32 modelID, const String& tag, CompAttr& rtn);

				/*
				* 函数功能： 根据条件查询构件guid
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& key [in] : 属性的key
				const String& val [in] : 属性的val
				CompInfoVec& [out] : 符合要求的构件列表
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompByProperty(uint32 modelID, const String& key, const String& val, CompInfoVec& rtn);

				/*
				* 函数功能： （精确）根据条件查询构件guid -- 分页
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& key [in] : 属性的key（精确）
				const String& val [in] : 属性的val（精确）
				uint32 recordNumPerPage [in] : 每页记录条数
				CompInfoPage& [out] : 符合要求的构件列表，分页结构，每次next获取下一个批次。结果在page.result
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompByProperty_Page(uint32 modelID, const String& key, const String& val, uint32 recordNumPerPage, CompInfoPage& page);

				/*
				* 函数功能： （val模糊）根据条件查询构件guid -- 分页
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				LikeColumn column [in] : 字段选择
				const String& val [in] : 属性的val（模糊）
				uint32 recordNumPerPage [in] : 每页记录条数
				CompInfoPage& [out] : 符合要求的构件列表，分页结构，每次next获取下一个批次。结果在page.result
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompByProperty_Like_Page(uint32 modelID, LikeColumn column, const String& val, uint32 recordNumPerPage, CompInfoPage& page);


				/*
				* 函数功能： 获取所有构件类别
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				CompTypeVec& [out] : 构件类别列表
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompType(uint32 modelID, CompTypeVec& rtn);

				/*
				* 函数功能： 根据构件类别获取构件guid
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				uint32 compTypeID [in] : 构件类别ID，这个值从CompTypeVec里得到
				CompInfoVec& [out] : 符合要求的构件列表
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompByType(uint32 modelID, uint32 compTypeID, CompInfoVec& rtn);

				/*
				* 函数功能： 根据构件类别获取构件guid -- 分页
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				uint32 compTypeID [in] : 构件类别ID，这个值从CompTypeVec里得到
				uint32 recordNumPerPage [in] : 每页记录条数
				CompInfoPage& [out] : 符合要求的构件列表，分页结构，每次next获取下一个批次。结果在page.result
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompByType_Page(uint32 modelID, uint32 compTypeID, uint32 recordNumPerPage, CompInfoPage& page);

				/*
				* 函数功能： 查询楼层信息
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				Floors floors [out] : 楼层信息
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelFloors(uint32 modelID, Floors& floors);

				/*
				* 函数功能： 根据楼层查询构件
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				uint32 floorFDID [in] : 楼层ID，通过Floor结构获取
				uint32 recordNumPerPage [in] : 每页记录条数
				CompInfoPage& [out] : 符合要求的构件列表，分页结构，每次next获取下一个批次。结果在page.result
				* 返 回 值：true成功，false失败
				*/
				bool queryPModelCompByFloor_Page(uint32 modelID, uint32 floorFDID, uint32 recordNumPerPage, CompInfoPage& page);

				/*
				* 函数功能： 更新构件属性
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& guid [in] : 属性guid，这个值从CompAttr的PropertySet里得到
				const String& key [in] : 属性key，要求更析的属性名称
				const String& val [in] : 属性val，要求更析的属性值
				* 返 回 值：true成功，false失败
				*/
				bool updatePModelProperty(uint32 modelID, const String& guid, const String& key, const String& val);

				/*
				* 函数功能： 添加构件属性（添加propertyset的一个property）
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& compGuid [in] : 构件guid
				const String& proGuid [in] : 属性guid，这个值从CompAttr的PropertySet里得到
				const String& key [in] : 属性key，要求更析的属性名称
				const String& val [in] : 属性val，要求更析的属性值
				* 返 回 值：true成功，false失败
				*/
				bool insertPModelProperty(uint32 modelID, const String& compGuid, const String& proGuid, const String& key, const String& val);

				/*
				* 函数功能： 添加构件属性（添加propertyset）
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& compGuid [in] : 构件guid
				const PropertySet& proSet [in] : 属性集

				注意：PropertySet结构中的guid存在，则效果和insertPModelProperty类似，如果不存在，则创建一个新的

				* 返 回 值：true成功，false失败
				*/
				bool insertPModelPropertySet(uint32 modelID, const String& compGuid, const PropertySet& proSet);

				/*
				* 函数功能： 删除构件属性（删除propertyset的一个property）
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& compGuid [in] : 构件guid
				const String& guid [in] : 属性guid，这个值从CompAttr的PropertySet里得到
				const String& key [in] : 属性key，要求删除的属性名称
				* 返 回 值：true成功，false失败
				*/
				bool deletePModelProperty(uint32 modelID, const String& compGuid, const String& guid, const String& key);

				/*
				* 函数功能： 删除构件属性集（删除propertyset）
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& compGuid [in] : 构件guid
				const String& guid [in] : 属性guid，这个值从CompAttr的PropertySet里得到
				* 返 回 值：true成功，false失败
				*/
				bool deletePModelPropertySet(uint32 modelID, const String& compGuid, const String& guid);

				/*
				* 函数功能： 添加某人对PModel的访问权限
				* 参    数：
				const String& author [in] : 赋予权限的人
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				* 返 回 值：true成功，false失败
				*/
				bool addPModelPermission(const String& author, uint32 modelID);

				/*
				* 函数功能： 去掉某人对PModel的访问权限
				* 参    数：
				const String& author [in] : 赋予权限的人
				uint32 modelID [in] : 需要赋予权限的PModel	
				* 返 回 值：true成功，false失败
				*/
				void removePModelPermission(const String& author, uint32 modelID);

				/*
				* 函数功能： 某人是否有权限访问PModel
				* 参    数：
				const String& author [in] : 赋予权限的人
				uint32 modelID [in] : 需要赋予权限的PModel	
				* 返 回 值：true成功，false失败
				*/
				bool hasPModelPermission(const String& author, uint32 modelID);

				/*
				* 函数功能： 插入时间任务
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				const String& Task [in] : 任务。t.guid在一个modelID中不能重复
				* 返 回 值：0失败，返回任务ID。可做为子节点的parentID
				*/
				uint32 insertPModelTask(uint32 modelID, const Task& t);

				/*
				* 函数功能： 删除时间任务
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				uint32 taskID [in] : 任务ID
				注意：删除组节点，子节点会一起删除
				* 返 回 值：
				*/
				void removePModelTask(uint32 modelID, uint32 taskID);

				/*
				* 函数功能： 根据分页方式，获取PModel所有任务集  -- 分页
				* 参    数：
				uint32 modelID [in] : PModel的ID，可以根据existsPModel获取
				uint32 recordNumPerPage [in] : 分页记录条数
				TaskPage& page [out] : 任务集合。结果在page.result，如果有子任务，结构体会有体现
				* 返 回 值：false失败，true成功
				*/
				bool queryPModelTask_Page(uint32 modelID, uint32 recordNumPerPage, TaskPage& page);

				
				/*
				* 函数功能： 内存释放
				*/
				static void releaseModelTree(ModelTree* t);
				static void releaseModelTreeVec(ModelTreeVec& treeVec);

#ifndef FDB_LINUX			
				ModelTreeVec queryPModelChildrenTree(uint32 modelID, uint32 treeID);
				ModelTreeVec queryPModelChildrenTree(const String& modelName, uint32 treeID);

				ModelTree* queryPModelAllTree(const String& modelName);
				ModelTree* queryPModelAllTree(uint32 modelID);

				void queryPModelTreeComponentTimeline(uint32 modelID, ComponentTimeline& timeline);
				void queryPModelTreeComponentTimeline(const String& modelName, ComponentTimeline& timeline);

				uint32 insertPModelTreeRecord(uint32 modelID, ModelTree* tree);
				void deletePModelTreeRecord(uint32 modelID, const String& guid);
#endif

				uint32 createPModel(const String& modelName);
				void deletePModel(uint32 modelID);

				bool updatePModelTreeBox(uint32 modelID, const String& guid, SimpleBound& box);
				uint32 insertPModelTree(uint32 modelID, ModelTree* tree, uint32 no);
				void deletePModelTree(uint32 modelID, const String& guid);

				bool insertPModelLayer(uint32 modelID, const String& guid ,const String& name);
				void deletePModelLayer(uint32 modelID, const String& guid);

				uint32 insertPModelProperty_priv(uint32 modelID, const String& guid, const String& name, const String& key, const String& val);
				uint32 insertPModelPropertyBatch(uint32 modelID, PropertyInsertBatch& batch);
		
				uint32 insertPModelCompType(uint32 modelID, const String& guid , const String& tag, const String& predefinedType, const String& name, uint32 typeID);
				void deletePModelCompType(uint32 modelID, const String& guid);

				uint32 insertPModelPropertyRef(uint32 modelID, uint32 compFDID, uint32 objectFDID, uint32 refTypeID, uint32 proFDID, const String& compGuid, const String& compName);
				bool insertPModelPropertyRefBatch(uint32 modelID, PropertyRefInsertBatch& batch);
				void deletePModelPropertyRef(uint32 modelID, const String& guid,const String& objGuid);

				bool insertPModelOpeningElem(uint32 modelID, const String& guid ,const String& compGuid, const String& layerGuid, const String& objectType, const String& objectPlacement, const String& name);
				void deletePModelOpeningElem(uint32 modelID, const String& guid);

				uint32 insertPModelCompTypeMetaInfo(uint32 modelID, const String& compTypeName);
				void deletePModelCompTypeMetaInfo(uint32 modelID, uint32 compTypeID);

				uint32 insertPModelAttr(uint32 modelID, const String& guid , const String& name, const String& compTypeGuid, const String& layerGuid, bool hasOpeningElem, const String& GBCODE
										,const String& objectType, const String& objectPlacement, const String& tag, uint32 floorFDID);
				void deletePModelAttr(uint32 modelID, const String& guid);

				uint32 insertPModelFloor(uint32 modelID, const String& guid, const String& name, const String& objectPlacement, const String& longName, const String& compositionType, const String& elevation);
				bool deletePModelFloor(uint32 modelID, const String& guid);

				void dropPModelIndex(uint32 modelID);
				bool buildPModelIndex(uint32 modelID, String& errorIndex);

				uint32 getCompFDID(uint32 modelID, const String& guid, String& name);
				uint32 getProFDID(uint32 modelID, const String& guid, const String& key);
				void getProFDID(uint32 modelID, const String& guid, std::vector<int>& ids);

				bool updateTopTreeBound(uint32 modelID, SimpleBound& bound);
			protected:
#ifndef FDB_LINUX
				uint32 insertMeshRecord(ModelRecord* record, bool& alreadyExist);
				uint32 insertTextureRecord(uint32 modelID, const FD::Kernel::MemoryDataStreamPtr& origStream, const FD::Kernel::MemoryDataStreamPtr& thumbStream);

				void deleteMeshRecord(uint32 modelID);
				void deleteTextureRecord(uint32 modelID);

				void getRefTextureIDs(uint32 modelID, FD::Kernel::IntVector& ids);
				bool existRefTexture(uint32 texID);

				void getCompositeModelTreeTabName(uint32 modelID, String& treeTab, String& attrTab);
#endif
				bool createTab(const String& sqlScript);
				void getAttrTabName(uint32 modelID, String& treeTab, String& attrTab, String& metaTab);
				void getPModelTreeTabName(uint32 modelID, String& treeTab, String& attrTab, String& metaTab, String& layerTab, String& compTypeTab, String& propertyRefTab, String& propertyTab, String& openingElemTab, String& compMetaInfo, String& floorTab);
				String getPermissionTab();

				bool queryTaskChildren(uint32 modelID, uint32 taskID, TaskVec& tv);
				bool refTaskChild(uint32 modelID, uint32 taskID);
				bool unRefTaskChild(uint32 modelID, uint32 taskID);
				uint32 getTaskParentID(uint32 modelID, uint32 taskID);

				bool insertPModelProperty(uint32 modelID, const String& compGuid, const String& proGuid, const String& name, const String& key, const String& val);
			protected:

				ModelDB(ModelDataSource* ds, const String& dbName);
				C_DISABLE_COPY(ModelDB);

				void refTransNum();

				ModelDataSource* mpDataSource;
				String mDBName;
				String mMeshTab;
				String mTextureTab;
				String mTextureRefTab;
				String mMetaInfoTab;
				uint32 mDBID;
				SameNameMode mSameNameMode;
				uint32 mTransNum;
				uint32 mCurrentTransNum;
				bool mAutoTrans;
			};
			
		}
	}
}


#endif
